package com.sys.system.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sys.common.config.ThirdAuthConfigProperties;
import com.sys.common.core.domain.entity.SysUser;
import com.sys.common.core.domain.model.LoginUser;
import com.sys.common.exception.ServiceException;
import com.sys.common.utils.AuthUtils;
import com.sys.common.utils.SecurityUtils;
import com.sys.system.domain.SysUserThirdAuth;
import com.sys.system.domain.fo.BindThirdAuthFO;
import com.sys.system.domain.vo.ThirdAuthVO;
import com.sys.system.mapper.SysUserMapper;
import com.sys.system.mapper.SysUserThirdAuthMapper;
import com.sys.system.service.ISysUserThirdAuthService;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.cache.AuthDefaultStateCache;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 第三方授权Service业务层处理
 *
 * @author LGY
 * @date 2025-04-18
 */
@Slf4j
@Service
public class SysUserThirdAuthServiceImpl extends ServiceImpl<SysUserThirdAuthMapper, SysUserThirdAuth> implements ISysUserThirdAuthService {
    @Autowired
    private SysUserThirdAuthMapper sysUserThirdAuthMapper;
    @Autowired
    private ThirdAuthConfigProperties thirdAuthConfigProperties;
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 查询第三方授权
     *
     * @param id 第三方授权主键
     * @return 第三方授权
     */
    @Override
    public SysUserThirdAuth selectSysUserThirdAuthById(String id) {
        return this.getById(id);
    }

    /**
     * 查询第三方授权列表
     *
     * @param sysUserThirdAuth 第三方授权
     * @return 第三方授权
     */
    @Override
    public List<SysUserThirdAuth> selectSysUserThirdAuthList(SysUserThirdAuth sysUserThirdAuth) {
        return sysUserThirdAuthMapper.selectSysUserThirdAuthList(sysUserThirdAuth);
    }

    /**
     * 新增第三方授权
     *
     * @param sysUserThirdAuth 第三方授权
     * @return 结果
     */

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void insertSysUserThirdAuth(SysUserThirdAuth sysUserThirdAuth) {
        this.save(sysUserThirdAuth);
    }

    /**
     * 修改第三方授权
     *
     * @param sysUserThirdAuth 第三方授权
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateSysUserThirdAuth(SysUserThirdAuth sysUserThirdAuth) {
        this.updateById(sysUserThirdAuth);
    }

    /**
     * 批量删除第三方授权
     *
     * @param ids 需要删除的第三方授权主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteSysUserThirdAuthByIds(String[] ids) {
        this.removeBatchByIds(Arrays.asList(ids));
    }

    @Override
    public List<ThirdAuthVO> getThirdAuths(String userId) {
        List<ThirdAuthConfigProperties.App> apps = thirdAuthConfigProperties.getApps();
        if (CollectionUtils.isEmpty(apps)) {
            return new ArrayList<>();
        }
        List<SysUserThirdAuth> bindAuthList = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(SysUserThirdAuth::getUserId, userId)
                .list();
        return apps.stream().map(app -> {
            ThirdAuthVO thirdAuthVO = new ThirdAuthVO();
            AuthRequest authRequest = AuthUtils.getAuthRequest(app, AuthDefaultStateCache.INSTANCE);
            thirdAuthVO.setTitle(app.getType())
                    .setIcon(app.getIcon())
                    .setClientId(app.getClientId())
                    .setAuthUrl(authRequest.authorize(AuthStateUtils.createState()))
                    .setHasBind(!CollectionUtils.isEmpty(bindAuthList) && bindAuthList.stream().map(SysUserThirdAuth::getSource).toList().contains(app.getType()));
            return thirdAuthVO;
        }).toList();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void bindThirdAuth(BindThirdAuthFO bindThirdAuthFO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        List<SysUserThirdAuth> sysUserThirdAuthList = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(SysUserThirdAuth::getUserId, loginUser.getId())
                .eq(SysUserThirdAuth::getSource, bindThirdAuthFO.getType())
                .list();
        if (!CollectionUtils.isEmpty(sysUserThirdAuthList)) {
            log.info("已绑定该第三方登录平台，无需重复绑定");
            return;
        }
        Map<String, ThirdAuthConfigProperties.App> supportAppMap =
                thirdAuthConfigProperties.getApps().stream().collect(Collectors.toMap(ThirdAuthConfigProperties.App::getType, app -> app));
        ThirdAuthConfigProperties.App bindApp = supportAppMap.get(bindThirdAuthFO.getType());
        if (bindApp == null) {
            throw new ServiceException("未配置该平台的授权");
        }
        AuthRequest authRequest = AuthUtils.getAuthRequest(bindApp, AuthDefaultStateCache.INSTANCE);
        AuthCallback authCallback = AuthCallback.builder()
                .state(bindThirdAuthFO.getState())
                .code(bindThirdAuthFO.getCode())
                .build();
        AuthResponse<AuthUser> resp = authRequest.login(authCallback);
        if (!resp.ok()) {
            throw new ServiceException("绑定第三方登录异常，请联系管理员");
        }
        SysUserThirdAuth sysUserThirdAuth = new SysUserThirdAuth();
        sysUserThirdAuth.setUserId(loginUser.getId())
                .setUuid(resp.getData().getUuid())
                .setSource(bindThirdAuthFO.getType());
        this.save(sysUserThirdAuth);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void unbindThirdAuth(BindThirdAuthFO bindThirdAuthFO) {
        new LambdaUpdateChainWrapper<>(baseMapper)
                .eq(SysUserThirdAuth::getUserId, SecurityUtils.getUserId())
                .eq(SysUserThirdAuth::getSource, bindThirdAuthFO.getType())
                .remove();
    }

    @Override
    public SysUser getUserByThirdTypeAndUUid(String thirdAuthUUId, String type) {
        List<SysUserThirdAuth> sysUserThirdAuths = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(SysUserThirdAuth::getUuid, thirdAuthUUId)
                .eq(SysUserThirdAuth::getSource, type)
                .list();
        if (CollectionUtils.isEmpty(sysUserThirdAuths)) {
            return null;
        }
        return sysUserMapper.selectUserById(sysUserThirdAuths.get(0).getUserId());
    }
}